#!/bin/sh

# mkinitrd for 2.4/2.6 Kernel by Jim Gifford <scripts@j555.com>
# modified by Tobias Powalowski <tpowa@archlinux.org> for Arch Linux usage

# defaults
USB_TIMEOUT=10

if [ "$1" == "--skip-config" ]; then
	# don't read the local config, we're building a kernel package
	shift
else
	[ -f /etc/mkinitrd.conf ] && . /etc/mkinitrd.conf
fi
# compatibility for old config names
[ "$REMOVE_CRYPT" == "1" ] && REMOVE_DM="1"

INITRDFS="ext2"
ROOT_DIR=
# size of initrd in KB
IMAGE_SIZE=16384

QUIET=0
outp() {
	if ! [ "$QUIET" == "1" ]; then
		echo "$*"
	fi
}

#
# Usage Menu
#
usage () {
	echo "$0 <kernel_version> [options]"
	echo ""
	echo "  Where <kernel_version> is one of:"
	echo "    auto                        build for the installed Arch kernel"
	echo "    full                        build with all possible modules"
	echo "    kernel_version={version}    use kernel version (no autodetect)"
	echo ""
	echo "  Options:"
	echo "    --ide                    exclude ide modules"
	echo "    --scsi                   exclude scsi modules"
	echo "    --usb                    exclude usb modules"
	echo "    --cdrom                  exclude cdrom modules"
	echo "    --fw                     exclude firewire modules"
	echo "    --raid                   exclude raid modules"
	echo "    --dm                     exclude device mapper modules"
	echo "    --remove-module=MODULE   exclude MODULE"
	echo "    --add-module=MODULE      include MODULE"
	echo "    --lvm-root=ROOT_DEV      use ROOT_DEV as the LVM root device"
	echo "    --root-dir=ROOT_DIR      look for modules in ROOT_DIR/lib/modules"
	echo "                             instead of /lib/modules"
	echo "    --quiet                  no status output during initrd generation"
	echo "    --show                   show modules that are included in initrd"
	echo ""
	exit 1
}

# $1 = base name
# $2 = start index
# $3 = finish index
# $4 = device major
# $5 = device minor of first index
mkblkdevs() {
	minor=$5
	for i in `seq $2 $3`; do
		devname="/dev/$1$i"
		echo "mknod $devname b $4 $minor" >>$LINUXRC
		minor=$(($minor+1))
	done
	minor=$(($5-1))
	if [ $minor -ge 0 ]; then
		echo "mknod /dev/$1 b $4 $minor" >>$LINUXRC
	fi
}

createscsiraid() {
# COMPAQ module ccsis
MINOR="-16"
	for i in `seq 0 4`; do
		MINOR=$((MINOR+16))
		echo "mknod /dev/cciss/c0d$i b 104 $MINOR"  >>$LINUXRC
		for k in `seq 1 8`; do
			echo "mknod /dev/cciss/c0d${i}p${k} b 104 $k"  >>$LINUXRC
		done
	done
# COMPAQ module cpqarray 
MINOR="-16"
	for i in `seq 0 4`; do
		MINOR=$((MINOR+16))
		echo "mknod /dev/ida/c0d$i b 72 $MINOR"  >>$LINUXRC
		for k in `seq 1 8`; do
			echo "mknod /dev/ida/c0d${i}p${k} b 72 $k"  >>$LINUXRC
		done
	done
# DAC module DAC960
MINOR="-8"
	for i in `seq 0 4`; do
		MINOR=$((MINOR+8))
		echo "mknod /dev/rd/c0d$i b 48 $MINOR"  >>$LINUXRC
		for k in `seq 1 8`; do
			echo "mknod /dev/rd/c0d${i}p${k} b 48 $k"  >>$LINUXRC
		done
	done
}

MK_LOOP_DEVS=0
mkloopdevs() {
	MK_LOOP_DEVS=1
	for i in `seq 0 7`; do
		mknod /dev/loop$i b 7 $i
	done
}


#
# Input Check
#
[ "$1" == "" ] && usage

# check this parameter separately so we know whether to be quiet from the get-go
for arg in $*; do
	if [ "$arg" == "--quiet" ]; then
		QUIET=1
	fi
done

outp "Checking Input..."

while [ $# -gt 0 ]; do
	case $1 in
		-ide|--ide)
			REMOVE_IDE="1"
			outp "    Removing IDE Modules"
			;;

		-scsi|--scsi)
			REMOVE_SCSI="1"
			outp "    Removing SCSI Modules"
			;;

		-cdrom|--cdrom)
			REMOVE_CDROM="1"
			outp "    Removing CDROM Modules"
			;;

		-usb|--usb)
			REMOVE_USB="1"
			outp "    Removing USB Modules"
			;;

		-raid|--raid)
			REMOVE_RAID="1"
			outp "    Removing RAID Modules"
			;;

		-fw|--fw)
			REMOVE_FW="1"
			outp "    Removing FW Modules"
			;;

		-dm|-crypt|--dm)
			REMOVE_DM="1"
			outp "    Removing DM Modules"
			;;
		
		auto)
			# first, check that ramdisk size is correct
			KERNEL_RAMDISK_SIZE=`grep CONFIG_BLK_DEV_RAM_SIZE= /boot/kconfig26 | cut -d= -f2`
			if [ $KERNEL_RAMDISK_SIZE -lt $IMAGE_SIZE ]; then
				echo "ERROR: Your ramdisk size ($KERNEL_RAMDISK_SIZE KB) is too low! It must be at least $IMAGE_SIZE KB." >&2
				exit 1
			fi
			grep "version" $ROOT_DIR/boot/kconfig26 > /tmp/kernelversion
			sed -i -e 's/.*:\ //g' /tmp/kernelversion
			sed -i -e 's/$/-ARCH/g' /tmp/kernelversion
			KERNEL_VERSION="`cat /tmp/kernelversion`"
			outp "    Making image for standard Arch kernel ($KERNEL_VERSION)..."
			KER_VER_REL="`echo $KERNEL_VERSION | grep -o 2.6`"
			KERNEL_INITRD="initrd26"
			;;

		kernel_version=*)
			KERNEL_VERSION="`echo $1 | awk -F= '{print $2;}'`"
			outp "    Making image for kernel $KERNEL_VERSION..."
			KER_VER_REL="`echo $KERNEL_VERSION | grep -o 2.6`"
			KERNEL_INITRD="initrd-${KERNEL_VERSION}"
			;;

		-module=*|--remove-module=*)
			if [ "$REMOVE_MODULE" == "" ]; then
				REMOVE_MODULE="`echo $1 | awk -F= '{print $2;}'`"
				outp "    Removing Module $REMOVE_MODULE"
			else
				NEW_MODULE="`echo $1 | awk -F= '{print $2;}'`"
				outp "    Removing Module $NEW_MODULE"
				REMOVE_MODULE="$REMOVE_MODULE $NEW_MODULE"
			fi
			;;

		+module=*|--add-module=*)
			if [ "$ADD_MODULE" == "" ]; then
				ADD_MODULE="`echo $1 | awk -F= '{print $2;}'`"
				outp "    Adding Module $ADD_MODULE"
			else
				NEW_MODULE="`echo $1 | awk -F= '{print $2;}'`"
				outp "    Adding Module $NEW_MODULE"
				ADD_MODULE="$ADD_MODULE $NEW_MODULE"
			fi
			;;

		lvm-root=*|--lvm-root=*)
			LVM_ROOT="`echo $1 | awk -F= '{print $2;}'`"
			;;

		--root-dir=*)
			ROOT_DIR="`echo $1 | awk -F= '{print $2;}'`"
			;;

		full|legacy)
			grep "version" $ROOT_DIR/boot/kconfig26 > /tmp/kernelversion
			sed -i -e 's/.*:\ //g' /tmp/kernelversion
			sed -i -e 's/$/-ARCH/g' /tmp/kernelversion
			KERNEL_VERSION="`cat /tmp/kernelversion`"
			KER_VER_REL="`echo $KERNEL_VERSION | grep -o 2.6`"
			KERNEL_INITRD="initrd26-$1"
			# Disable AUTODETECTION
			AUTODETECT=
			# Disable whole subsystems by adding "1"
			REMOVE_IDE=
			REMOVE_SCSI=
			REMOVE_SATA=
			REMOVE_CDROM=
			REMOVE_USB=
			REMOVE_FW=
			REMOVE_RAID=
			REMOVE_DM=
			REMOVE_FS=
			# Define which modules are needed by adding "moduleX moduleY"
			# empty means all modules are included if they are not disabled above!
			HOSTCONTROLLER_IDE=
			HOSTCONTROLLER_SCSI=
			HOSTCONTROLLER_SATA=
			HOSTCONTROLLER_USB=
			FILESYSTEMS=
			outp "    Building $1 initrd for Arch standard kernel"
			outp "      (includes all possible modules)"
			;;

		-show|--show)
			LIST_MODULES=1
			;;

		--quiet)
			# already set above
			;;

		*)
			usage
			;;
		esac
	shift
done

outp "Setting up Parameters..."

#
# Get Root Device Information
#
if [ "$ROOT_DEVICE" == "" ]; then
	ROOT_DEVICE="$(awk '/^[ \t]*[^#]/ { if ($2 == "/") { print $1; }}' /etc/fstab)"
fi

if [ "$LVM_ROOT" ]; then
	REMOVE_DM="0"
fi

#
# Module Files
#
if [ "$KER_VER_REL" == "2.6" ]; then
	EXTENSION="ko"
fi

rm -f /tmp/foundmodules
rm -f /tmp/copiedmodules

#
# Find Dependencies
#
finddep () {
	for module in $MODULES; do
		if [ "$KER_VER_REL" == "2.6" ]; then
			modprobe --set-version=$KERNEL_VERSION --show-depends $module 2>/dev/null | \
			sed -ne "s#^insmod.*/\(.*\)\.$EXTENSION.*#\1#p" >> /tmp/foundmodules
		fi
	done
}

#
# Find Modules
#
find_module() {
	FIND_MOD=$1
	SEARCH="`find $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel -name $FIND_MOD`"
}

#
# Add or Remove IDE Modules
#
if [ "$REMOVE_IDE" == "1" ]; then
	PRE_IDE=""
	IDE_MODULES=""
	POST_IDE=""
else
	if [ -d $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/ide/pci ]; then
		if [ "$HOSTCONTROLLER_IDE" == "" ]; then
			if [ "$AUTODETECT" == "1" ]; then
				for check in `hwdetect --kernel_version=$KERNEL_VERSION --ide`; do
					IDE_MODULE="`echo $check`"
					IDE_MODULES="$IDE_MODULES $IDE_MODULE"
				done
			else
				CHECK="`ls -1 $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/ide/pci/* > /tmp/ide; \
				sed -i -e 's|/.*/||g' -e 's/.ko//g' /tmp/ide; cat /tmp/ide`"
				for check in $CHECK; do	
					IDE_MODULE="`echo $check`"
					IDE_MODULES="$IDE_MODULES $IDE_MODULE"
				done
			fi
		else
			IDE_MODULES="$HOSTCONTROLLER_IDE"
		fi

		if [ "$REMOVE_CDROM" == "1" ]; then
			if ! [ "$IDE_MODULES" == "" ]; then
				POST_IDE="ide-disk ide-floppy"
			else
				POST_IDE=""
			fi
			
		else
			if ! [ "$IDE_MODULES" == "" ]; then
				POST_IDE="ide-disk cdrom ide-cd ide-floppy"
			else
				POST_IDE=""
			fi
			
		fi
	fi
fi

#
# Add or Remove SCSI Modules
#
if [ "$REMOVE_SCSI" == "1" ]; then
	PRE_SCSI=""
	SCSI_MODULES=""
	POST_SCSI=""
else
	if [ -d $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/scsi ]; then
		if [ "$HOSTCONTROLLER_SCSI" == "" ]; then
			if [ "$AUTODETECT" == "1" ]; then
				for check in `hwdetect --kernel_version=$KERNEL_VERSION --scsi`; do
					SCSI_MODULE="`echo $check`"
					SCSI_MODULES="$SCSI_MODULES $SCSI_MODULE"
				done
				if ! [ "$SCSI_MODULES" == "" ]; then
					PRE_SCSI="sd_mod"
				fi
			else
				CHECK="`find $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/scsi/ -name "*.ko" ! -name "sata*" ! -name "ide-scsi*" ! -name "libata*" ! -name "*_cs*" >/tmp/scsi; \
				find $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/message/fusion/ -name "*.ko" >>/tmp/scsi ; \
				find $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/block/ -name "*.ko" ! -name "*s8x.ko" ! -name "*nbd.ko" ! -name "*pktcdvd.ko" >> /tmp/scsi ; \
				sed -i -e 's|/.*/||g' -e 's/.ko//g' /tmp/scsi; cat /tmp/scsi`"
				for check in $CHECK; do	
				SCSI_MODULE="`echo $check`"
				SCSI_MODULES="$SCSI_MODULES $SCSI_MODULE"
				done
				PRE_SCSI="sd_mod"
			fi
		else
			PRE_SCSI="sd_mod"
			SCSI_MODULES="$HOSTCONTROLLER_SCSI"
		fi

		if [ "$REMOVE_CDROM" == "1" ]; then
			POST_SCSI=""
		else
			if ! [ "$SCSI_MODULES" == "" ]; then
				POST_SCSI="cdrom sr_mod"
			else
				POST_SCSI=""
			fi
		fi
	fi
fi

#
# Add or Remove SATA Modules
#
if [ "$REMOVE_SATA" == "1" ]; then
	PRE_SATA=""
	SATA_MODULES=""
	POST_SATA=""
else
	if [ -d $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/scsi ]; then
		if [ "$HOSTCONTROLLER_SATA" == "" ]; then
			if [ "$AUTODETECT" == "1" ]; then
				for check in `hwdetect --kernel_version=$KERNEL_VERSION --sata`; do
					SATA_MODULE="`echo $check`"
					SATA_MODULES="$SATA_MODULES $SATA_MODULE"
				done
				if ! [ "$SATA_MODULES" == "" ]; then
					PRE_SATA="sd_mod libata"
				fi
			else
				CHECK="`find $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/scsi/ -name "sata*" ! -name "ide-scsi*" ! -name "*_cs*" >/tmp/sata; \
				find $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/block/ -name "*s8x.ko"; \
				sed -i -e 's|/.*/||g' -e 's/.ko//g' /tmp/sata; cat /tmp/sata`"
				for check in $CHECK; do	
				SATA_MODULE="`echo $check`"
				SATA_MODULES="$SATA_MODULES $SATA_MODULE"
				done
				PRE_SATA="sd_mod libata"
			fi
		else
			PRE_SATA="sd_mod libata"
			SATA_MODULES="$HOSTCONTROLLER_SATA"
		fi
	fi
fi

#
# Add or Remove RAID Modules
#
if [ "$REMOVE_RAID" == "1" ]; then
	PRE_RAID=""
	RAID_MODULES=""
	POST_RAID=""
else
	if [ -d $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/md ]; then
		PRE_RAID=""
		CHECK="`find $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/md/ ! -name "dm*.ko" >/tmp/raid; \
			sed -i -e 's|/.*/||g' -e 's/.ko//g' /tmp/raid; cat /tmp/raid`"
		for check in $CHECK; do	
			RAID_MODULE="`echo $check`"
			RAID_MODULES="$RAID_MODULES $RAID_MODULE"
		done
	fi
fi

#
# Add or Remove DM Modules
#
if [ "$REMOVE_DM" == "1" ]; then
	PRE_DM=""
	DM_MODULES=""
	POST_DM=""
else
	PRE_DM="aes-i586"
	if [ -d $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/md ]; then
		CHECK="`find $ROOT_DIR/lib/modules/$KERNEL_VERSION/kernel/drivers/md/ -name "dm*.ko" >/tmp/crypt; \
			sed -i -e 's|/.*/||g' -e 's/.ko//g' /tmp/crypt; cat /tmp/crypt`"
		for check in $CHECK; do	
			DM_MODULE="`echo $check`"
			DM_MODULES="$DM_MODULES $DM_MODULE"
		done
	fi
fi

#
# Add or Remove USB Modules
#
if [ "$REMOVE_USB" == "1" ]; then
	PRE_USB=""
	USB_MODULES=""
	POST_USB=""
else
	PRE_USB="sd_mod usbcore"
		
	if  [ "$HOSTCONTROLLER_USB" == "" ]; then
		if [ "$AUTODETECT" == "1" ]; then
			for check in `hwdetect --kernel_version=$KERNEL_VERSION --usb`; do
				USB_MODULE="`echo $check`"
				USB_MODULES="$USB_MODULES $USB_MODULE"
			done
		else
			USB_MODULES="ehci-hcd ohci-hcd uhci-hcd"
		fi
	else
		USB_MODULES="$HOSTCONTROLLER_USB"
	fi
	POST_USB="usb-storage usbhid"
fi

# Add or Remove FW Modules
#
if [ "$REMOVE_FW" == "1" ]; then
	PRE_FW=""
	FW_MODULES=""
	POST_FW=""
else
	PRE_FW="sd_mod ieee1394"
	FW_MODULES="ohci1394"
	POST_FW="sbp2"
fi

#
# Add or Remove FS Modules
#
if [ "$REMOVE_FS" == "1" ]; then
	PRE_FS=""
	FS_MODULES=""
	POST_FS=""
else
	PRE_FS=""
	if  [ "$FILESYSTEMS" == "" ]; then
		FS_MODULES="ext3 jfs reiserfs xfs"
	else
		FS_MODULES="$FILESYSTEMS"
	fi	
	POST_FS=""
fi

#
# Create Module Groups
#
IDE_MODULES_GROUP="$PRE_IDE $IDE_MODULES $POST_IDE"
SCSI_MODULES_GROUP="$PRE_SCSI $SCSI_MODULES $POST_SCSI"
SATA_MODULES_GROUP="$PRE_SATA $SATA_MODULES $POST_SATA"
RAID_MODULES_GROUP="$PRE_RAID $RAID_MODULES $POST_RAID"
DM_MODULES_GROUP="$PRE_DM $DM_MODULES $POST_DM"
USB_MODULES_GROUP="$PRE_USB $USB_MODULES $POST_USB"
FW_MODULES_GROUP="$PRE_FW $FW_MODULES $POST_FW"
FS_MODULES_GROUP="$PRE_FS $FS_MODULES $POST_FS"

#
# List of All Needed Modules
#
MODULES="$IDE_MODULES_GROUP $SCSI_MODULES_GROUP $SATA_MODULES_GROUP $RAID_MODULES_GROUP $DM_MODULES_GROUP $USB_MODULES_GROUP $FW_MODULES_GROUP $FS_MODULES_GROUP $ADD_MODULE"

#
# Find the module dependencies
#
finddep

#
# Initrd name
#
MOUNT_IMAGE="/tmp/initrd.$$"
IMAGE="/tmp/initrd.img-$$"
MOUNT_POINT="/tmp/initrd.mnt-$$"
LINUXRC="$MOUNT_IMAGE/linuxrc"
INITRD="$ROOT_DIR/boot/$KERNEL_INITRD.img"

#
# Check for Valid Kernel
#
if [ -e $ROOT_DIR/lib/modules/$KERNEL_VERSION ]; then
	outp "    $ROOT_DIR/lib/modules/$KERNEL_VERSION found"
else
	echo "ERROR: $ROOT_DIR/lib/modules/$KERNEL_VERSION does not exist!" >&2
	exit 1
fi

#
# Create Image and setup Loopback
#
dd if=/dev/zero of=$IMAGE bs=1k count=$IMAGE_SIZE 2> /dev/null

if [ "$INITRDFS" == "ext2" ]; then
	# Create loopback devices if necessary
	if ! [ -e /dev/loop/0 -o -e /dev/loop0 ]; then
		outp "    Creating loopback devices (temporarily)"
		mkloopdevs
	fi
	# Setup loopback
	for device_number in 0 1 2 3 4 5 6 7 8; do
		if losetup /dev/loop/$device_number $IMAGE 2>/dev/null; then
			LOOP_DEVICE=/dev/loop/$device_number
			break
		fi
		if losetup /dev/loop$device_number $IMAGE 2>/dev/null; then
			LOOP_DEVICE=/dev/loop$device_number
			break
		fi
	done

	if [ "$device_number" = "8" ]; then
		rm -rf $MOUNT_POINT $IMAGE
		echo "ERROR: All of your loopback devices are in use!" >&2
		exit 1
	fi
fi

#
# Make sure the initrd filesystem is in the kernel
#
if [ "$INITRDFS" == "ext2" ]; then
	find_module "ext2.$EXTENSION"

	if [ "$SEARCH" == "ext2.$EXTENSION" ]; then
		echo "ERROR: ext2 support MUST be built in to your kernel!" >&2
		echo "       It cannot be loaded as a module." >&2
		exit 1
	else
		echo y | mkfs.ext2 $LOOP_DEVICE $IMAGE_SIZE > /dev/null 2> /dev/null
	fi
fi

outp "Creating Initial RAM Disk..."

#
# Create initrd directory
#
mkdir -p $MOUNT_POINT

if [ "$INITRDFS" == "ext2" ]; then
	mount -t $INITRDFS $LOOP_DEVICE $MOUNT_POINT || {
		echo "ERROR: Can't get a loopback device!" >&2
		exit 1
	}
fi

#
# Create Directories
#
mkdir -p $MOUNT_IMAGE
mkdir -p $MOUNT_IMAGE/{bin,dev,etc,lib,new_root,proc,sys}
mkdir -p $MOUNT_IMAGE/dev/{rd,cciss,ida}

# Basic tty support (needed for cryptsetup's stdin)
mknod $MOUNT_IMAGE/dev/console c 5 1
mknod $MOUNT_IMAGE/dev/tty c 5 0

rm -rf $MOUNT_POINT/lost+found

#
# Copy Static Programs
#
if ! [ "$REMOVE_DM" == "1" ]; then
	if ! [ "$CRYPT_DEVICE" == "" ]; then
		if [ -f /sbin/cryptsetup.static ]; then
			cp -a /sbin/cryptsetup.static $MOUNT_IMAGE/bin/cryptsetup
		else
			outp "Warning: cryptsetup is not installed -- encrypted filesystems will not work"
		fi
	fi
fi

if ! [ "$REMOVE_RAID" == "1" ]; then
	if [ -f /sbin/mdadm.static ]; then
		cp -a /sbin/mdadm.static $MOUNT_IMAGE/bin/mdadm
		echo "DEVICE partitions" >$MOUNT_IMAGE/etc/mdadm.conf
		/sbin/mdadm -D --scan >>$MOUNT_IMAGE/etc/mdadm.conf
	else
		outp "Warning: mdadm is not installed -- RAID arrays will not work"
	fi
fi

cp -a /sbin/busybox $MOUNT_IMAGE/bin/busybox
cd $MOUNT_IMAGE/bin/
ln busybox $MOUNT_IMAGE/bin/awk
ln busybox $MOUNT_IMAGE/bin/cat
ln busybox $MOUNT_IMAGE/bin/chroot
ln busybox $MOUNT_IMAGE/bin/cp
ln busybox $MOUNT_IMAGE/bin/echo
ln busybox $MOUNT_IMAGE/bin/insmod
ln busybox $MOUNT_IMAGE/bin/ls
ln busybox $MOUNT_IMAGE/bin/mount
ln busybox $MOUNT_IMAGE/bin/mkdir
ln busybox $MOUNT_IMAGE/bin/mknod
ln busybox $MOUNT_IMAGE/bin/mkrootdev
ln busybox $MOUNT_IMAGE/bin/umount
ln busybox $MOUNT_IMAGE/bin/pivot_root
ln busybox $MOUNT_IMAGE/bin/reboot
ln busybox $MOUNT_IMAGE/bin/rm
ln busybox $MOUNT_IMAGE/bin/sed
ln busybox $MOUNT_IMAGE/bin/sleep
ln busybox $MOUNT_IMAGE/bin/sh
ln busybox $MOUNT_IMAGE/bin/test
# add lvm tools if required
if [ "$LVM_ROOT" ]; then
	if [ -r /sbin/lvm.static ]; then
		cp -a /sbin/lvm.static $MOUNT_IMAGE/bin/lvm
		mkdir -p $MOUNT_IMAGE/etc/lvm
		cp -a /etc/lvm/lvm.conf $MOUNT_IMAGE/etc/lvm/lvm.conf
		HAVE_LVM=1
	else
		outp "Warning: mdadm is not installed -- LVM root will not work!"
		HAVE_LVM=0
	fi
fi
# add filesystem check to avoid VFS warnings during boot
if [ -f /sbin/fsck.static ]; then
	cp -a /sbin/fsck.static $MOUNT_IMAGE/bin/fsck
	echo "none none none defaults 0 0" >> $MOUNT_IMAGE/etc/fstab
	mkdir $MOUNT_IMAGE/sbin
	touch $MOUNT_IMAGE/sbin/fsck.ext2
	touch $MOUNT_IMAGE/sbin/fsck.ext3
	touch $MOUNT_IMAGE/sbin/fsck.jfs
	touch $MOUNT_IMAGE/sbin/fsck.reiserfs
	touch $MOUNT_IMAGE/sbin/fsck.xfs
	HAVE_FSCK=1
else
	outp "Warning: e2fsprogs is not installed -- Filesystem detection will not work"
	HAVE_FSCK=0
fi

#
# Copy Modules
#
rm -f /tmp/copiedmodules

MODULES="`cat /tmp/foundmodules`"
for MODULE in $MODULES; do
	echo "$MODULE" | {
		IFS=':' read module
		find_module "$module.$EXTENSION"
		REMOVE_MOD="0"

		if ! [ "$SEARCH" == "" ]; then
			if ! [ -e $MOUNT_IMAGE/lib/$module.$EXTENSION ]; then
				for remove in $REMOVE_MODULE; do
					if [ "$remove" == "$module" ]; then
						REMOVE_MOD="1"
					fi
					# since '-' and '_' are interchangeable, we have to cover both
					if [ "`echo $remove | grep '-'`" ]; then
						remove="`echo $remove | sed 's|-|_|g'`"
						[ "$remove" == "$module" ] && REMOVE_MOD="1"
					elif [ "`echo $remove | grep '_'`" ]; then
						remove="`echo $remove | sed 's|_|-|g'`"
						[ "$remove" == "$module" ] && REMOVE_MOD="1"
					fi
				done
	
				if [ "$REMOVE_MOD" != "1" ]; then
					cp $SEARCH $MOUNT_IMAGE/lib
					echo "$module" >> /tmp/copiedmodules
					if [ "$LIST_MODULES" == "1" ]; then
						echo "$module"
					fi
				fi
			fi
		fi
	}
done

#
# Creating linuxrc startup script
#
echo "#!/bin/sh" > $LINUXRC
echo "echo \"Initial RAMDISK Loading Modules...\"" >> $LINUXRC
echo "mount -n -t proc none /proc" >> $LINUXRC

if [ "$KER_VER_REL" == "2.6" ]; then
	echo "mount -n -t sysfs none /sys" >> $LINUXRC
fi
# create basic device nodes
echo "mknod /dev/null c 1 3" >> $LINUXRC
echo "mknod /dev/ram0 b 1 0" >> $LINUXRC
echo "mknod /dev/tty1 c 4 1" >> $LINUXRC
echo "mknod /dev/tty2 c 4 2" >> $LINUXRC
echo "mknod /dev/tty3 c 4 3" >> $LINUXRC
echo "mknod /dev/tty4 c 4 4" >> $LINUXRC
echo "mkdir /dev/mapper" >> $LINUXRC
echo "mknod /dev/mapper/control c 10 63" >> $LINUXRC
# create IDE devices
mkblkdevs hda 1 12 3 1
mkblkdevs hdb 1 12 3 65
mkblkdevs hdc 1 12 22 1
mkblkdevs hdd 1 12 22 65
mkblkdevs hde 1 12 33 1
mkblkdevs hdf 1 12 33 65
mkblkdevs hdg 1 12 34 1
mkblkdevs hdh 1 12 34 65
# create SCSI/FW/USB devices
mkblkdevs sda 1 12 8 1
mkblkdevs sdb 1 12 8 17
mkblkdevs sdc 1 12 8 33
mkblkdevs sdd 1 12 8 49
mkblkdevs sde 1 12 8 65
mkblkdevs sdf 1 12 8 81
mkblkdevs sdg 1 12 8 113
mkblkdevs sdh 1 12 8 129
# create MD devices
mkblkdevs md 0 15 9 0
# create scsi raid devices
createscsiraid

MODULES="`cat /tmp/copiedmodules`"
for MODULE in $MODULES; do
	echo "$MODULE" | {
		IFS=':' read module
		echo "insmod /lib/$module.$EXTENSION > /dev/null 2>&1" >> $LINUXRC
	}
done

if ! [ "$REMOVE_USB" == "1" ]; then
	echo 'echo "Loading USB Subsystem..."' >> $LINUXRC
	echo "echo \"    (waiting $USB_TIMEOUT seconds for devices to settle)\"" >>$LINUXRC
	echo "sleep $USB_TIMEOUT" >> $LINUXRC
fi
	
# set up RAID root device
if ! [ "$REMOVE_RAID" == "1" ]; then
	echo "/bin/mdadm --assemble --run --scan" >>$LINUXRC
fi

# set up encrypted root device
if ! [ "$REMOVE_DM" == "1" ]; then
	if ! [ "$CRYPT_DEVICE" == "" ]; then
		echo 'echo' >>$LINUXRC
		echo 'echo "A PASSWORD IS REQUIRED TO ACCESS ROOT FILESYSTEM"' >>$LINUXRC
		echo 'echo' >>$LINUXRC
		echo "if \`/bin/cryptsetup isLuks $CRYPT_DEVICE 2>/dev/null\`; then" >>$LINUXRC
		echo "  /bin/cryptsetup $CRYPT_OPTIONS luksOpen $CRYPT_DEVICE root" >>$LINUXRC
		echo 'else' >>$LINUXRC
		echo "  /bin/cryptsetup $CRYPT_OPTIONS create root $CRYPT_DEVICE" >>$LINUXRC
		echo 'fi' >>$LINUXRC
		echo 'if test $? -ne 0; then' >>$LINUXRC
		echo '	echo "Password Verification FAILED"' >>$LINUXRC
		echo '	exit 1' >>$LINUXRC
		echo 'fi' >>$LINUXRC
	fi
fi
# set up LVM root device
if [ "$LVM_ROOT" -a "$HAVE_LVM" = "1" ]; then
    echo 'echo "Scanning logical volumes..."' >>$LINUXRC
    echo "lvm vgscan --ignorelockingfailure" >>$LINUXRC
    echo 'echo "Activating logical volumes..."' >>$LINUXRC
    echo "lvm vgchange --ignorelockingfailure -ay" >>$LINUXRC
    echo "ROOT_DEV=$ROOT_DEVICE" >>$LINUXRC
else
    #echo "ROOT_DEV=\`cat /proc/cmdline | awk -Froot= '{print \$2}' | awk '{print \$1}'\`" >>$LINUXRC
    echo "ROOT_DEV=/dev/root" >>$LINUXRC
    echo "mkrootdev /dev/root" >>$LINUXRC
fi
echo "echo 0x0100 > /proc/sys/kernel/real-root-dev" >>$LINUXRC
if [ "$HAVE_FSCK" = "1" ]; then
	echo "mount -t \`/bin/fsck -NT \$ROOT_DEV | awk -Ffsck. '{print \$2}' | awk '{print \$1}'\` -n -o ro \$ROOT_DEV /new_root" >>$LINUXRC
else
	echo "mount -t auto -n -o ro \$ROOT_DEV /new_root" >>$LINUXRC
fi
echo "pivot_root /new_root /new_root/initrd" >> $LINUXRC
echo "umount /initrd/sys" >> $LINUXRC
echo "umount /initrd/proc" >> $LINUXRC
# fix libata for using atapi enabled
sed -i -e 's:\(libata.ko\):\1 atapi_enabled=1:' $LINUXRC
chmod +x $LINUXRC

echo "/sbin/busybox echo \"Initial RAMDISK Loading Completed...\"" >> $LINUXRC

# Unmount and Compress initrd
#
(cd $MOUNT_IMAGE; tar cf - .) | (cd $MOUNT_POINT; tar xf -)

if [ "$INITRDFS" == "ext2" ]; then
	umount $MOUNT_POINT
	losetup -d $LOOP_DEVICE
	if [ "$MK_LOOP_DEVS" == "1" ]; then
		rm -f /dev/loop[0-7]
	fi
fi

# do we show post-install instructions?
[ -e $INITRD ] || INSTRUCTIONS=1

gzip -9 < $IMAGE > $INITRD

# Remove all temp files
#
rm -rf $MOUNT_IMAGE $MOUNT_POINT $IMAGE
rm -f /tmp/foundmodules
rm -f /tmp/copiedmodules
rm -f /tmp/config
rm -f /tmp/kernelversion
rm -f /tmp/ide
rm -f /tmp/scsi
rm -f /tmp/sata
rm -f /tmp/raid
rm -f /tmp/crypt

if [ -e $INITRD -a "$INSTRUCTIONS" == "1" ]; then
	echo ">>> Your initrd was created at $INITRD"
	echo ""
	echo ">>> INITRD UPGRADE INSTRUCTIONS"
	echo ""
	echo "   1. Make sure your /etc/fstab does not use DevFS-style names anymore" 
	echo "   2. If you ever need to manually rebuild your initrd, run 'mkinitrd auto'"
	echo "   3. IMPORTANT:  Add the proper 'initrd' line to your bootloader config"
	echo "     GRUB Example (/boot/grub/menu.lst):"
	echo ""
	echo "        title     Arch Linux, kernel 2.6.x"
	echo "        root      (hd?,?)"
	echo "        kernel    /vmlinuz26 root=$ROOT_DEVICE ro"
	echo "        initrd    /$KERNEL_INITRD.img"
	echo ""
	echo "     LILO Example (/etc/lilo.conf):"
	echo ""
	echo "        image=/boot/vmlinuz26"
	echo "            label=arch"
	echo "            root=$ROOT_DEVICE"
	echo "            read-only"
	echo "            initrd=/boot/$KERNEL_INITRD.img"
	echo ""
fi

exit 0

